-- Display Pos and When player is holding the mapkit
-- TODO: Display Pos and when the minimap is shown
-- Based on http://repo.or.cz/minetest_orienteering.git

if not minetest.get_modpath("map") then return end

local S = minetest.get_translator("orienteering")
local mod_map = minetest.get_modpath("map") -- map mod from Minetest Game

local orienteering = {}
orienteering.playerhuds = {}
orienteering.settings = {}
orienteering.settings.speed_unit = S("m/s")
orienteering.settings.length_unit = S("m")
orienteering.settings.hud_pos = { x = 0.8, y = 0.75 }
orienteering.settings.hud_offset = { x = 0, y = 15 }
orienteering.settings.hud_alignment = { x = 1, y = 0 }

local set = tonumber(minetest.settings:get("orienteering_hud_pos_x"))
if set then orienteering.settings.hud_pos.x = set end
set = tonumber(minetest.settings:get("orienteering_hud_pos_y"))
if set then orienteering.settings.hud_pos.y = set end
set = tonumber(minetest.settings:get("orienteering_hud_offset_x"))
if set then orienteering.settings.hud_offset.x = set end
set = tonumber(minetest.settings:get("orienteering_hud_offset_y"))
if set then orienteering.settings.hud_offset.y = set end
set = minetest.settings:get("orienteering_hud_alignment")
if set == "left" then
	orienteering.settings.hud_alignment.x = 1
elseif set == "center" then
	orienteering.settings.hud_alignment.x = 0
elseif set == "right" then
	orienteering.settings.hud_alignment.x = -1
end

local o_lines = 5 -- Number of lines in HUD

-- Helper function to switch between 12h and 24 mode for the time
function orienteering.toggle_time_mode(itemstack, user, pointed_thing)
	--[[ Player attribute “orienteering:twelve”:
	* "true": Use 12h mode for time
	* "false" or unset: Use 24h mode for time ]]
	if user:get_meta():get_string("orienteering:twelve") == "true" then
		user:get_meta():set_string("orienteering:twelve", "false")
	else
		user:get_meta():set_string("orienteering:twelve", "true")
	end
	orienteering.update_hud_displays(user)
end


local use = S("Put this tool in your hotbar to see the data it provides.")
local use_time = S("Put this tool in your hotbar to make use of its functionality. Punch to toggle between 24-hour and 12-hour display for the time feature.")


-- Checks whether a certain orienteering tool is “active” and ready for use
function orienteering.show_hud(player)
	
  local wielded_item = player:get_wielded_item():get_name()

  if wielded_item == "map:mapping_kit" or string.sub(wielded_item, 0, 12) == "realcompass:" then
    return true
  end
  
	-- local hotbar = player:hud_get_hotbar_itemcount()
	-- for i=1, hotbar do
		-- if inv:get_stack("main", i):get_name() == item then
			-- return true
		-- end
	-- end

  -- local inv = player:get_inventory()
	-- if item == "map:mapping_kit" then
		-- return inv:contains_item("main", item)
	-- end

	return false
end

function orienteering.init_hud(player)
	local name = player:get_player_name()
	orienteering.playerhuds[name] = {}
	for i=1, o_lines do
		orienteering.playerhuds[name]["o_line"..i] = player:hud_add({
			hud_elem_type = "text",
			text = "",
			position = orienteering.settings.hud_pos,
			offset = { x = orienteering.settings.hud_offset.x, y = orienteering.settings.hud_offset.y + 20*(i-1) },
			alignment = orienteering.settings.hud_alignment,
			number = 0xFFFFFF,
			scale= { x = 100, y = 20 },
			z_index = 0,
		})
	end
end

function orienteering.update_hud_displays(player)

	local name = player:get_player_name()
  if not orienteering.show_hud(player) then
    for i=1, o_lines do
      player:hud_change(orienteering.playerhuds[name]["o_line"..i], "text", "")
    end
    return
  end
  
	local toDegrees=180/math.pi
	local gps, altimeter, triangulator, compass, sextant, watch, speedometer, quadcorder

	local str_pos, str_angles, str_time, str_speed
	local pos = vector.round(player:get_pos())

  str_pos = S("Coordinates: X=@1, Y=@2, Z=@3", pos.x, pos.y, pos.z)



	-- Yaw in Minetest goes counter-clockwise, which is opposite of how compasses work
  local player_yaw = player:get_look_horizontal()
	local yaw = 360-player_yaw*toDegrees
  -- local pitch = player:get_look_vertical()*toDegrees
  local ldv = player:get_look_dir()
  local lookdir = ""
  
  if ldv.z < -0.4 then lookdir = "S" -- (-Z)
  elseif ldv.z > 0.4 then lookdir = "N" -- (+Z)
  end
  if ldv.x > 0.4 then lookdir = lookdir .. "W" -- (+X)
  elseif ldv.x < -0.4 then lookdir = lookdir .. "E" -- (-X)
  end
  
  str_angles = S("Yaw: @1°", string.format("%.1f", yaw))
  str_angles = S("Yaw: @1°, @2 ( X=@3 Z=@4 )", string.format("%.1f", yaw), lookdir, string.format("%.1f", ldv.x), string.format("%.1f", ldv.z))

  -- str_angles = S("Pitch: @1°", string.format("%.1f", pitch))
	






	local time = minetest.get_timeofday()
  local totalminutes = time * 1440
  local minutes = totalminutes % 60
  local hours = math.floor((totalminutes - minutes) / 60)
  minutes = math.floor(minutes)
  local twelve = player:get_meta():get_string("orienteering:twelve") == "true"
  if twelve then
    if hours == 12 and minutes == 0 then
      str_time = S("Time: noon")
    elseif hours == 0 and minutes == 0 then
      str_time = S("Time: midnight")
    else
      local hours12 = math.fmod(hours, 12)
      if hours12 == 0 then hours12 = 12 end
      if hours >= 12 then
        str_time = S("Time: @1:@2 p.m.", string.format("%i", hours12), string.format("%02i", minutes))
      else
        str_time = S("Time: @1:@2 a.m.", string.format("%i", hours12), string.format("%02i", minutes))
      end
    end
  else
    str_time = S("Time: @1:@2", string.format("%02i", hours), string.format("%02i", minutes))
  end


  local strs = { str_pos, str_time, str_angles }
	local line = 1
	for i=1, o_lines do
		if strs[i] and strs[i] ~= "" then
			player:hud_change(orienteering.playerhuds[name]["o_line"..line], "text", strs[i])
			line = line + 1
		end
	end
	for l=line, o_lines do
		player:hud_change(orienteering.playerhuds[name]["o_line"..l], "text", "")
	end

end

minetest.register_on_newplayer(orienteering.init_hud)
minetest.register_on_joinplayer(orienteering.init_hud)

minetest.register_on_leaveplayer(function(player)
	orienteering.playerhuds[player:get_player_name()] = nil
end)


-- on_use = function(itemstack, user, pointed_thing)
  -- map.update_hud_flags(user)
-- end

local updatetimer = 0
minetest.register_globalstep(function(dtime)
	updatetimer = updatetimer + dtime
	if updatetimer > 0.1 then
    local players = minetest.get_connected_players()
		for i=1, #players do
      orienteering.update_hud_displays(players[i])
		end
		updatetimer = updatetimer - dtime
	end
end)

